package org.jeecg.modules.yinsheng.utils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jeecg.modules.yinsheng.annotation.DecimalMax;
import org.jeecg.modules.yinsheng.annotation.DecimalMin;
import org.jeecg.modules.yinsheng.annotation.Length;
import org.jeecg.modules.yinsheng.annotation.NotBlank;
import org.jeecg.modules.yinsheng.annotation.NotNull;
import org.jeecg.modules.yinsheng.annotation.Pattern;


/**
 * @ClassName ValidateUtils
 * @Description 校验请求信息
 * @Author linxl
 * @Date 2021/4/6 11:31
 * @Version 1.0
 */
public class ValidateUtils {
	private final static Logger LOGGER = Logger.getLogger(ValidateUtils.class.getName());

	// validate the fields
	public static void validate(Object obj) throws YsChannelClientException {
		try {
			// 获取当前类
			Class<?> clazz = obj.getClass();
			// 获取当前对象obj的所有属性域
			Field[] fields_this = clazz.getDeclaredFields();
			// 获取对象obj直接父类的所有属性域
			Field[] fields_super = clazz.getSuperclass().getDeclaredFields();
			Set<Field[]> set = new HashSet<>();
			set.add(fields_this);
			set.add(fields_super);
			for (Field[] fields : set) {
				for (Field field : fields) {
					// 非空校验
					if (field.isAnnotationPresent(NotBlank.class)) {
						// 获取当前属性
						String o = getObj(field, obj);
						// 获取注解
						NotBlank notBlank = field.getAnnotation(NotBlank.class);
						// 判空
						if (StringUtils.isBlank(o)) {
							LOGGER.log(Level.SEVERE, "变量： " + field.getName() + "不能为空");
							throw new YsChannelClientException(YsChannelEnum.PARAM_VERIFY_FAIL.getCode(),
									notBlank.message());
						}
					}
					// null校验
					if (field.isAnnotationPresent(NotNull.class)) {
						// 获取当前属性
						Object o = getObj(field, obj);
						// 获取注解
						NotNull notNull = field.getAnnotation(NotNull.class);
						// 判空
						if (o == null) {
							LOGGER.log(Level.SEVERE, "变量： " + field.getName() + "不能为null");
							throw new YsChannelClientException(YsChannelEnum.PARAM_VERIFY_FAIL.getCode(),
									notNull.message());
						}
					}

					// 判断该注解是不是存在于这个元素上面,长度校验
					if (field.isAnnotationPresent(Length.class)) {
						// 获取当前属性
						String o = getObj(field, obj);
						if (o == null) {
							continue;
						}
						// 获取注解
						Length length = field.getAnnotation(Length.class);
						// 比较长度
						if (length.max() < o.length() || length.min() > o.length()) {
							LOGGER.log(Level.SEVERE, "变量： " + field.getName() + "不满足长度要求！");
							throw new YsChannelClientException(YsChannelEnum.PARAM_VERIFY_FAIL.getCode(),
									length.message());
						}
					}
					// 格式校验
					if (field.isAnnotationPresent(Pattern.class)) {
						// 获取当前属性
						String o = getObj(field, obj);
						if (o == null) {
							continue;
						}
						// 获取注解
						Pattern pattern = field.getAnnotation(Pattern.class);
						// 校验正则
						if (!java.util.regex.Pattern.matches(pattern.regexp(), o)) {
							LOGGER.log(Level.SEVERE, "变量： " + field.getName() + "不符合格式要求");
							throw new YsChannelClientException(YsChannelEnum.PARAM_VERIFY_FAIL.getCode(),
									pattern.message());
						}
					}

					// 金额格式校验
					if (field.isAnnotationPresent(DecimalMin.class)) {
						// 获取当前属性
						Double o = getObj(field, obj);
						if (o == null) {
							continue;
						}
						// 获取注解
						DecimalMin decimalMin = field.getAnnotation(DecimalMin.class);
						// 校验
						BigDecimal mini = new BigDecimal(decimalMin.value());
						BigDecimal b2 = BigDecimal.valueOf(o);
						if (mini.compareTo(b2) > 0) {
							LOGGER.log(Level.SEVERE, "变量： " + field.getName() + "不符合格式要求");
							throw new YsChannelClientException(YsChannelEnum.PARAM_VERIFY_FAIL.getCode(),
									decimalMin.message());
						}
					}

					// 金额格式校验
					if (field.isAnnotationPresent(DecimalMax.class)) {
						// 获取当前属性
						Double o = getObj(field, obj);
						if (o == null) {
							continue;
						}
						// 获取注解
						DecimalMax decimalMax = field.getAnnotation(DecimalMax.class);
						// 校验
						BigDecimal max = new BigDecimal(decimalMax.value());
						BigDecimal b2 = BigDecimal.valueOf(o);
						if (max.compareTo(b2) < 0) {
							LOGGER.log(Level.SEVERE, "变量： " + field.getName() + "不符合格式要求");
							throw new YsChannelClientException(YsChannelEnum.PARAM_VERIFY_FAIL.getCode(),
									decimalMax.message());
						}
					}
				}
			}
		} catch (IllegalAccessException e) {
			LOGGER.log(Level.SEVERE, "变量可见性设置错误", e);
			throw new YsChannelClientException(YsChannelEnum.PARAM_VERIFY_FAIL.getCode(),
					YsChannelEnum.PARAM_VERIFY_FAIL.getMessage(), e);
		}
	}

	private static <T> T getObj(Field field, Object obj) throws IllegalAccessException {
		// 获取属性名称
		String varName = field.getName();
		// 获取属性可见性
		boolean access = field.isAccessible();
		// 设置可见性
		if (!access) {
			field.setAccessible(true);
		}
		// 从obj中获取field变量
		T o = (T) field.get(obj);
		// LOGGER.log(Level.INFO, "变量： " + varName + " = " + o);
		// 恢复原有的可见性
		if (!access) {
			field.setAccessible(false);
		}
		return o;
	}

}
